treeview: Get rid of child surfaces
authorMatthias Clasen <mclasen@redhat.com>
Sun, 29 Jul 2018 13:43:00 +0000 (09:43 -0400)
committerMatthias Clasen <mclasen@redhat.com>
Sun, 29 Jul 2018 19:23:41 +0000 (15:23 -0400)
Drop the drag-highlight and drag surfaces. The highlighting
is broken anyway, so just drop it for now. And for dragging
the header button, we can just position it properly, that
works just as well as this reparenting approach.

gtk/gtktreeview.c

index f9ccd551c48e995788686a75fdc0853db76df7f7..40af08657a2b256a46b86b87140c645415b96045 100644 (file)
@@ -387,10 +387,9 @@ struct _GtkTreeViewPrivate
   guint scroll_timeout;
 
   /* Interactive Header reordering */
-  GdkSurface *drag_surface;
-  GdkSurface *drag_highlight_surface;
   GtkTreeViewColumn *drag_column;
   gint drag_column_x;
+  gint drag_column_y;
 
   /* Interactive Header Resizing */
   gint drag_pos;
@@ -2250,20 +2249,6 @@ gtk_tree_view_unrealize (GtkWidget *widget)
       priv->typeselect_flush_timeout = 0;
     }
 
-  if (priv->drag_surface)
-    {
-      gtk_widget_unregister_surface (widget, priv->drag_surface);
-      gdk_surface_destroy (priv->drag_surface);
-      priv->drag_surface = NULL;
-    }
-
-  if (priv->drag_highlight_surface)
-    {
-      gtk_widget_unregister_surface (widget, priv->drag_highlight_surface);
-      gdk_surface_destroy (priv->drag_highlight_surface);
-      priv->drag_highlight_surface = NULL;
-    }
-
   GTK_WIDGET_CLASS (gtk_tree_view_parent_class)->unrealize (widget);
 }
 
@@ -2454,11 +2439,13 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
       gint column_width;
 
       column = list->data;
+      column_width = _gtk_tree_view_column_request_width (column);
 
-      if (!gtk_tree_view_column_get_visible (column) || column == tree_view->priv->drag_column)
+      if (!gtk_tree_view_column_get_visible (column))
        continue;
 
-      column_width = _gtk_tree_view_column_request_width (column);
+      if (column == tree_view->priv->drag_column)
+        goto next;
 
       if (gtk_tree_view_column_get_expand (column))
        {
@@ -2493,7 +2480,7 @@ gtk_tree_view_size_allocate_columns (GtkWidget *widget)
       else
         _gtk_tree_view_column_allocate (column, width + x_offset,
                                         column_width, tree_view->priv->header_height);
-
+  next:
       width += column_width;
     }
 
@@ -2512,7 +2499,8 @@ static void
 gtk_tree_view_size_allocate_drag_column (GtkWidget *widget)
 {
   GtkTreeView *tree_view = GTK_TREE_VIEW (widget);
-  GtkAllocation drag_allocation;
+  GtkAllocation allocation;
+  int baseline;
   GtkWidget *button;
 
   if (tree_view->priv->drag_column == NULL)
@@ -2520,11 +2508,13 @@ gtk_tree_view_size_allocate_drag_column (GtkWidget *widget)
 
   button = gtk_tree_view_column_get_button (tree_view->priv->drag_column);
 
-  drag_allocation.x = 0;
-  drag_allocation.y = 0;
-  drag_allocation.width = gdk_surface_get_width (tree_view->priv->drag_surface);
-  drag_allocation.height = gdk_surface_get_height (tree_view->priv->drag_surface);
-  gtk_widget_size_allocate (button, &drag_allocation, -1);
+  allocation.x = tree_view->priv->drag_column_x;
+  allocation.y = tree_view->priv->drag_column_y;
+  allocation.width = gtk_widget_get_allocated_width (button);
+  allocation.height = gtk_widget_get_allocated_height (button);
+  baseline = gtk_widget_get_allocated_baseline (button);
+
+  gtk_widget_size_allocate (button, &allocation, baseline);
 }
 
 static void
@@ -3175,12 +3165,8 @@ gtk_tree_view_button_release_drag_column (GtkTreeView *tree_view)
   context = gtk_widget_get_style_context (button);
   gtk_style_context_remove_class (context, GTK_STYLE_CLASS_DND);
 
-  g_object_ref (button);
-  gtk_container_remove (GTK_CONTAINER (tree_view), button);
   gtk_tree_view_update_button_position (tree_view, tree_view->priv->drag_column);
-  gtk_widget_set_parent (button, GTK_WIDGET (tree_view));
-  g_object_unref (button);
-  gtk_widget_queue_resize (widget);
+  gtk_widget_queue_allocate (widget);
 
   gtk_widget_grab_focus (button);
 
@@ -3199,9 +3185,6 @@ gtk_tree_view_button_release_drag_column (GtkTreeView *tree_view)
                                         tree_view->priv->cur_reorder->left_column);
     }
   tree_view->priv->drag_column = NULL;
-  gtk_widget_unregister_surface (widget, tree_view->priv->drag_surface);
-  gdk_surface_destroy (tree_view->priv->drag_surface);
-  tree_view->priv->drag_surface = NULL;
 
   for (l = tree_view->priv->column_drag_info; l != NULL; l = l->next)
     g_slice_free (GtkTreeViewColumnReorder, l->data);
@@ -3209,9 +3192,6 @@ gtk_tree_view_button_release_drag_column (GtkTreeView *tree_view)
   tree_view->priv->column_drag_info = NULL;
   tree_view->priv->cur_reorder = NULL;
 
-  if (tree_view->priv->drag_highlight_surface)
-    gdk_surface_hide (tree_view->priv->drag_highlight_surface);
-
   /* Reset our flags */
   tree_view->priv->drag_column_surface_state = DRAG_COLUMN_WINDOW_STATE_UNSET;
   tree_view->priv->in_column_drag = FALSE;
@@ -3254,13 +3234,7 @@ gtk_tree_view_column_drag_gesture_end (GtkGestureDrag *gesture,
     tree_view->priv->cur_reorder = NULL;
 
   if (tree_view->priv->in_column_drag)
-    {
-      GdkDevice *device;
-
-      gtk_tree_view_button_release_drag_column (tree_view);
-      device = gtk_gesture_get_device (GTK_GESTURE (gesture));
-      gdk_seat_ungrab (gdk_device_get_seat (device));
-    }
+    gtk_tree_view_button_release_drag_column (tree_view);
   else if (tree_view->priv->in_column_resize)
     gtk_tree_view_button_release_column_resize (tree_view);
 }
@@ -3556,248 +3530,6 @@ update_prelight (GtkTreeView *tree_view,
     prelight_or_select (tree_view, tree, node, x, y);
 }
 
-
-
-
-/* Our motion arrow is either a box (in the case of the original spot)
- * or an arrow.  It is expander_size wide.
- */
-/*
- * 11111111111111
- * 01111111111110
- * 00111111111100
- * 00011111111000
- * 00001111110000
- * 00000111100000
- * 00000111100000
- * 00000111100000
- * ~ ~ ~ ~ ~ ~ ~
- * 00000111100000
- * 00000111100000
- * 00000111100000
- * 00001111110000
- * 00011111111000
- * 00111111111100
- * 01111111111110
- * 11111111111111
- */
-
-static void
-gtk_tree_view_motion_draw_column_motion_arrow (GtkTreeView *tree_view)
-{
-  GtkTreeViewColumnReorder *reorder = tree_view->priv->cur_reorder;
-  GtkWidget *widget = GTK_WIDGET (tree_view);
-  cairo_surface_t *mask_image;
-  gint x;
-  gint y;
-  gint width;
-  gint height;
-  gint arrow_type = DRAG_COLUMN_WINDOW_STATE_UNSET;
-  cairo_t *cr;
-
-  if (!reorder ||
-      reorder->left_column == tree_view->priv->drag_column ||
-      reorder->right_column == tree_view->priv->drag_column)
-    arrow_type = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
-  else if (reorder->left_column || reorder->right_column)
-    {
-      GtkAllocation left_allocation, right_allocation;
-      GdkRectangle visible_rect;
-      GtkWidget *button;
-
-      gtk_tree_view_get_visible_rect (tree_view, &visible_rect);
-      if (reorder->left_column)
-        {
-         button = gtk_tree_view_column_get_button (reorder->left_column);
-          gtk_widget_get_allocation (button, &left_allocation);
-          x = left_allocation.x + left_allocation.width;
-        }
-      else
-        {
-         button = gtk_tree_view_column_get_button (reorder->right_column);
-          gtk_widget_get_allocation (button, &right_allocation);
-          x = right_allocation.x;
-        }
-
-      if (x < visible_rect.x)
-       arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT;
-      else if (x > visible_rect.x + visible_rect.width)
-       arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT;
-      else
-        arrow_type = DRAG_COLUMN_WINDOW_STATE_ARROW;
-    }
-
-  /* We want to draw the rectangle over the initial location. */
-  if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
-    {
-      if (tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
-       {
-          GtkAllocation drag_allocation;
-         GtkWidget    *button;
-
-         if (tree_view->priv->drag_highlight_surface)
-           {
-             gtk_widget_unregister_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface);
-             gdk_surface_destroy (tree_view->priv->drag_highlight_surface);
-           }
-
-         button = gtk_tree_view_column_get_button (tree_view->priv->drag_column);
-          gtk_widget_get_allocation (button, &drag_allocation);
-         width = drag_allocation.width;
-         height = drag_allocation.height;
-         tree_view->priv->drag_highlight_surface = gdk_surface_new_child (gtk_widget_get_surface (widget),
-                                                                         &(GdkRectangle){
-                                                                           tree_view->priv->drag_column_x,
-                                                                           0,
-                                                                           drag_allocation.width,
-                                                                           drag_allocation.height});
-         gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface);
-
-         tree_view->priv->drag_column_surface_state = DRAG_COLUMN_WINDOW_STATE_ORIGINAL;
-       }
-    }
-  else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW)
-    {
-      GtkAllocation button_allocation, allocation;
-      GtkWidget    *button;
-
-      width = gtk_tree_view_get_expander_size (tree_view);
-
-      /* Get x, y, width, height of arrow */
-      gtk_widget_get_allocation (widget, &allocation);
-      x = allocation.x;
-      y = allocation.y;
-
-      if (reorder->left_column)
-       {
-         button = gtk_tree_view_column_get_button (reorder->left_column);
-          gtk_widget_get_allocation (button, &button_allocation);
-         x += button_allocation.x + button_allocation.width - width/2;
-         height = button_allocation.height;
-       }
-      else
-       {
-         button = gtk_tree_view_column_get_button (reorder->right_column);
-          gtk_widget_get_allocation (button, &button_allocation);
-         x += button_allocation.x - width/2;
-         height = button_allocation.height;
-       }
-      y -= width/2; /* The arrow takes up only half the space */
-      height += width;
-
-      /* Create the new window */
-      if (tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ARROW)
-       {
-         if (tree_view->priv->drag_highlight_surface)
-           {
-             gtk_widget_unregister_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface);
-             gdk_surface_destroy (tree_view->priv->drag_highlight_surface);
-           }
-
-         tree_view->priv->drag_highlight_surface = gdk_surface_new_popup (gtk_widget_get_display (widget),
-                                                                         &(GdkRectangle) { x, y, width, height });
-         gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface);
-
-         mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
-
-          cr = cairo_create (mask_image);
-          cairo_move_to (cr, 0, 0);
-          cairo_line_to (cr, width, 0);
-          cairo_line_to (cr, width / 2., width / 2);
-          cairo_move_to (cr, 0, height);
-          cairo_line_to (cr, width, height);
-          cairo_line_to (cr, width / 2., height - width / 2.);
-          cairo_fill (cr);
-          cairo_destroy (cr);
-
-          cairo_surface_destroy (mask_image);
-       }
-
-      tree_view->priv->drag_column_surface_state = DRAG_COLUMN_WINDOW_STATE_ARROW;
-      gdk_surface_move (tree_view->priv->drag_highlight_surface, x, y);
-    }
-  else if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT ||
-          arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
-    {
-      GtkAllocation allocation;
-      GtkWidget    *button;
-      gint          expander_size;
-
-      expander_size = gtk_tree_view_get_expander_size (tree_view);
-
-      /* Get x, y, width, height of arrow */
-      width = expander_size/2; /* remember, the arrow only takes half the available width */
-      gtk_widget_get_allocation (widget, &allocation);
-      x = allocation.x;
-      y = allocation.y;
-      if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
-        {
-          x += gtk_widget_get_allocated_width (widget) - width;
-        }
-
-      if (reorder->left_column)
-        {
-         button = gtk_tree_view_column_get_button (reorder->left_column);
-          height = gtk_widget_get_allocated_height (button);
-        }
-      else
-        {
-         button = gtk_tree_view_column_get_button (reorder->right_column);
-          height = gtk_widget_get_allocated_height (button);
-        }
-
-      y -= expander_size;
-      height += 2 * expander_size;
-
-      /* Create the new window */
-      if (tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT &&
-         tree_view->priv->drag_column_surface_state != DRAG_COLUMN_WINDOW_STATE_ARROW_RIGHT)
-       {
-         if (tree_view->priv->drag_highlight_surface)
-           {
-             gtk_widget_unregister_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface);
-             gdk_surface_destroy (tree_view->priv->drag_highlight_surface);
-           }
-
-         tree_view->priv->drag_highlight_surface = gdk_surface_new_popup (gtk_widget_get_display (widget),
-                                                                         &(GdkRectangle) { x, y, width, height });
-         gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_highlight_surface);
-
-         mask_image = cairo_image_surface_create (CAIRO_FORMAT_A1, width, height);
-
-          cr = cairo_create (mask_image);
-          /* mirror if we're on the left */
-          if (arrow_type == DRAG_COLUMN_WINDOW_STATE_ARROW_LEFT)
-            {
-              cairo_translate (cr, width, 0);
-              cairo_scale (cr, -1, 1);
-            }
-          cairo_move_to (cr, 0, 0);
-          cairo_line_to (cr, width, width);
-          cairo_line_to (cr, 0, expander_size);
-          cairo_move_to (cr, 0, height);
-          cairo_line_to (cr, width, height - width);
-          cairo_line_to (cr, 0, height - expander_size);
-          cairo_fill (cr);
-          cairo_destroy (cr);
-
-          cairo_surface_destroy (mask_image);
-       }
-
-      tree_view->priv->drag_column_surface_state = arrow_type;
-      gdk_surface_move (tree_view->priv->drag_highlight_surface, x, y);
-   }
-  else
-    {
-      g_warning (G_STRLOC"Invalid GtkTreeViewColumnReorder struct");
-      gdk_surface_hide (tree_view->priv->drag_highlight_surface);
-      return;
-    }
-
-  gdk_surface_show (tree_view->priv->drag_highlight_surface);
-  gdk_surface_raise (tree_view->priv->drag_highlight_surface);
-}
-
 static gboolean
 gtk_tree_view_motion_resize_column (GtkTreeView *tree_view,
                                     gdouble      x,
@@ -3842,7 +3574,6 @@ gtk_tree_view_update_current_reorder (GtkTreeView *tree_view)
     }
 
   tree_view->priv->cur_reorder = reorder;
-  gtk_tree_view_motion_draw_column_motion_arrow (tree_view);
 }
 
 static void
@@ -3884,7 +3615,7 @@ gtk_tree_view_vertical_autoscroll (GtkTreeView *tree_view)
                             MAX (gtk_adjustment_get_value (tree_view->priv->vadjustment) + offset, 0.0));
 }
 
-static gboolean
+static void
 gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view)
 {
   GdkEventSequence *sequence;
@@ -3912,39 +3643,31 @@ gtk_tree_view_horizontal_autoscroll (GtkTreeView *tree_view)
 
   gtk_adjustment_set_value (tree_view->priv->hadjustment,
                             MAX (gtk_adjustment_get_value (tree_view->priv->hadjustment) + offset, 0.0));
-
-  return TRUE;
-
 }
 
-static gboolean
+static void
 gtk_tree_view_motion_drag_column (GtkTreeView *tree_view,
                                   gdouble      x,
                                   gdouble      y)
 {
   GtkTreeViewColumn *column = tree_view->priv->drag_column;
   GtkWidget *button;
-  gint win_x, win_y;
   gint width, button_width;
 
   button = gtk_tree_view_column_get_button (column);
   x += gtk_adjustment_get_value (tree_view->priv->hadjustment);
 
   /* Handle moving the header */
-  gdk_surface_get_position (tree_view->priv->drag_surface, &win_x, &win_y);
   width = gtk_widget_get_allocated_width (GTK_WIDGET (tree_view));
   button_width = gtk_widget_get_allocated_width (button);
-  win_x = CLAMP (x - _gtk_tree_view_column_get_drag_x (column), 0,
-                 MAX (tree_view->priv->width, width) - button_width);
-  gdk_surface_move (tree_view->priv->drag_surface, win_x, win_y);
-  gdk_surface_raise (tree_view->priv->drag_surface);
+  tree_view->priv->drag_column_x = CLAMP (x - _gtk_tree_view_column_get_drag_x (column), 0,
+                                          MAX (tree_view->priv->width, width) - button_width);
 
   /* autoscroll, if needed */
   gtk_tree_view_horizontal_autoscroll (tree_view);
   /* Update the current reorder position and arrow; */
   gtk_tree_view_update_current_reorder (tree_view);
-
-  return TRUE;
+  gtk_widget_queue_allocate (GTK_WIDGET (tree_view));
 }
 
 static void
@@ -5179,34 +4902,6 @@ gtk_tree_view_snapshot (GtkWidget   *widget,
 
   gtk_snapshot_pop (snapshot);
   
-#if 0
-  Thyis clearly does not work. priv->drag_highlight_surface is potentially a toplevel...
-  if (tree_view->priv->drag_highlight_surface)
-    {
-      GdkRGBA color;
-
-      gtk_style_context_get_color (context, &color);
-      cairo_save (cr);
-      if (tree_view->priv->drag_column_surface_state == DRAG_COLUMN_WINDOW_STATE_ORIGINAL)
-        {
-          cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0);
-          cairo_paint (cr);
-          gdk_cairo_set_source_rgba (cr, &color);
-          cairo_rectangle (cr,
-                           1, 1,
-                           gdk_surface_get_width (tree_view->priv->drag_highlight_surface) - 2,
-                           gdk_surface_get_height (tree_view->priv->drag_highlight_surface) - 2);
-          cairo_stroke (cr);
-        }
-      else
-        {
-          gdk_cairo_set_source_rgba (cr, &color);
-          cairo_paint (cr);
-        }
-      cairo_restore (cr);
-    }
-#endif
-
   gtk_snapshot_push_clip (snapshot,
                           &GRAPHENE_RECT_INIT(
                               0, 0,
@@ -5227,16 +4922,14 @@ gtk_tree_view_snapshot (GtkWidget   *widget,
       if (gtk_tree_view_column_get_visible (column))
         {
           button = gtk_tree_view_column_get_button (column);
-          gtk_widget_snapshot_child (widget,
-                                     button, snapshot);
+          gtk_widget_snapshot_child (widget, button, snapshot);
         }
     }
 
-  if (tree_view->priv->drag_surface)
+  if (tree_view->priv->drag_column)
     {
       button = gtk_tree_view_column_get_button (tree_view->priv->drag_column);
-      gtk_widget_snapshot_child (widget,
-                                 button, snapshot);
+      gtk_widget_snapshot_child (widget, button, snapshot);
     }
 
   gtk_style_context_restore (context);
@@ -9493,14 +9186,12 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
                                  GtkTreeViewColumn *column,
                                   GdkDevice         *device)
 {
-  GtkAllocation allocation;
   GtkAllocation button_allocation;
   GtkWidget *button;
   GtkStyleContext *context;
 
   g_return_if_fail (tree_view->priv->column_drag_info == NULL);
   g_return_if_fail (tree_view->priv->cur_reorder == NULL);
-  g_return_if_fail (tree_view->priv->drag_surface == NULL);
 
   gtk_tree_view_set_column_drag_info (tree_view, column);
 
@@ -9512,41 +9203,16 @@ _gtk_tree_view_column_start_drag (GtkTreeView       *tree_view,
   context = gtk_widget_get_style_context (button);
   gtk_style_context_add_class (context, GTK_STYLE_CLASS_DND);
 
-  gtk_widget_get_allocation (button, &button_allocation);
-  button_allocation.y = 0;
-
-  tree_view->priv->drag_surface = gdk_surface_new_child (gtk_widget_get_surface (GTK_WIDGET (tree_view)),
-                                                        &button_allocation);
-  gtk_widget_register_surface (GTK_WIDGET (tree_view), tree_view->priv->drag_surface);
-
-  /* Kids, don't try this at home */
-  g_object_ref (button);
-  gtk_container_remove (GTK_CONTAINER (tree_view), button);
-  gtk_widget_set_parent_surface (button, tree_view->priv->drag_surface);
-  gtk_widget_set_parent (button, GTK_WIDGET (tree_view));
-  g_object_unref (button);
-
   gtk_widget_get_allocation (button, &button_allocation);
   tree_view->priv->drag_column_x = button_allocation.x;
-  allocation = button_allocation;
-  allocation.x = 0;
-  gtk_widget_size_allocate (button, &allocation, -1);
+  tree_view->priv->drag_column_y = button_allocation.y;
 
   tree_view->priv->drag_column = column;
-  gdk_surface_show (tree_view->priv->drag_surface);
 
   gtk_widget_grab_focus (GTK_WIDGET (tree_view));
 
   tree_view->priv->in_column_drag = TRUE;
 
-  /* Widget reparenting above unmaps and indirectly breaks
-   * the implicit grab, replace it with an active one.
-   */
-  gdk_seat_grab (gdk_device_get_seat (device),
-                 tree_view->priv->drag_surface,
-                 GDK_SEAT_CAPABILITY_ALL, FALSE,
-                 NULL, NULL, NULL, NULL);
-
   gtk_gesture_set_state (tree_view->priv->column_drag_gesture,
                          GTK_EVENT_SEQUENCE_CLAIMED);
 }